package com.crscd.jdbc.senior.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Objects;
import java.util.Properties;
import javax.sql.DataSource;

/**
 * Created with IntelliJ IDEA. JDBC工具类（v2.0） 1. 维护一个连接池对象, 维护了一个线程绑定变量的ThreadLocal对象 2.
 * 对外提供在ThreadLocal中获取连接的方法 3. 对外提供回收连接的方法,回收的过程中，将要回收的连接从ThreadLocal移除
 * 注意：工具类进对外提供功能性的功能代码，所以方法均为静态方法 使用ThreadLocal就是为了一个线程在多次数据库操作中，使用的是同一个连接
 *
 * @description:
 * @author: liuziyang
 * @since: 10/23/25 10:15 AM
 * @modifiedBy:
 * @version: 1.0
 */
public class JdbcUtilv2 {
    private static final Logger LOGGER = LoggerFactory.getLogger(JdbcUtilv2.class);
  /** 创建连接池引用，因为要提供给当前项目的全局使用，所以创建为静态的 */
  private static final DataSource DATA_SOURCE;

  private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

  // 在项目启动时，即启动连接池对象，赋值给dataSource
  static {
    // 1. 创建Properties集合，用于存储外部配置文件的key和value值
    Properties properties = new Properties();

    try {
      // 2. 读取外部配置文件，获取输入流，加载到Properties集合里
      final InputStream inputStream =
          JdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
      properties.load(inputStream);
      // 3. 基于Properties集合构建DruidDataSource连接池
      DATA_SOURCE = DruidDataSourceFactory.createDataSource(properties);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Get connection connection.
   *
   * @return the connection
   */
  public static Connection getConnection() {
    try {
      // 在threadlocal中获取Connection
      Connection connection = threadLocal.get();
      // 如果threadlocal中没有存储Connection，也就是第一次获取
      if (Objects.isNull(connection)) {
        // 在连接池中获取一个连接，存储在threadlocal中
        connection = DATA_SOURCE.getConnection();
        threadLocal.set(connection);
      }
      return connection;
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /** Release. */
  public static void release() {
    try {
      final Connection connection = threadLocal.get();
      if (Objects.nonNull(connection)) {
        // 将threadlocal中的Connection对象移除
        threadLocal.remove();
        // 如果开启了事务的手动提交，操作完毕后，应该在归还连接前设置自动连接
        connection.setAutoCommit(true);
        // 将connection对象归还连接池
        connection.close();
      }
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }
}
